﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;
using Microsoft.Xna.Framework.Input;

namespace Utils.StageManagement
{
    public class StageManager : DrawableGameComponent
    {
        struct StageTransition {
            public TransitionType type;
            public Stage fromStage;
            public Stage toStage;
        }

        List<Stage> activeStages = new List<Stage>();
        List<StageTransition> activeTransition = new List<StageTransition>();
        Texture2D blankTexture;
        DTimeManager dTimeManager = new DTimeManager();

        public StageManager(Game game)
            : base(game){}

        public override void Initialize()
        {
            base.Initialize();
            Stage.TransitionEvent += OnTransitionEvent;
        }

        protected override void LoadContent()
        {
            ContentManager content = Game.Content;

            blankTexture = content.Load<Texture2D>("Textures/blank");
        }

        public void OnTransitionEvent(Object sender, StageTransitionEvent e) 
        {
            StageTransition transition = new StageTransition();
            transition.fromStage = (Stage)sender;
            transition.toStage = e.ToStage;
            transition.type = e.TransitionType;

            activeTransition.Add(transition);
        }

        public void AddStage(Stage stage)
        {
            activeStages.Add(stage);
            stage.LoadContent();
            stage.Init();
        }

        public void RemoveStage(Stage stage)
        {
            stage.Shutdown();
            stage.UnloadContent();
            activeStages.Remove(stage);
        }

        public override void Update(GameTime gameTime)
        {
            dTimeManager.UpdateDTimeMultiplier();
            float dTime = (float)gameTime.ElapsedGameTime.TotalSeconds * dTimeManager.DTimeMultiplier;

            // Transition Management
            if(activeTransition.Count > 0)
            {
                StageTransition transition = activeTransition[0];
                if (transition.toStage != activeStages[activeStages.Count - 1])
                {
                    // if the previous stage is done transitioning out or the type is popup
                    if (transition.type == TransitionType.PopUp
                        || transition.fromStage.StageState == Stage.State.Dead)
                    {
                        if (transition.type == TransitionType.Return)
                        {
                            RemoveStage(transition.fromStage);
                            if (transition.toStage.CoveredByOther)
                            {
                                transition.toStage.StartTransitionIntro();
                                transition.toStage.Reveal();
                            }
                            else
                            {
                                transition.toStage.ToForeground();
                            }
                        }
                        else
                        {
                            if (transition.type == TransitionType.PopUp)
                            {
                                transition.fromStage.ToBackground();
                            }
                            else
                            {
                                transition.fromStage.Hide();
                            }

                            transition.toStage.StartTransitionIntro();
                            AddStage(transition.toStage);
                        }
                    }
                }
                else
                {
                    // if the new stage is done transitioning in, transition is finished
                    if (transition.toStage.StageState == Stage.State.Active)
                    {
                        if (activeTransition[0].type == TransitionType.Replace)
                        {
                            RemoveStage(transition.fromStage);
                        }
                        activeTransition.RemoveAt(0);
                    }
                }
            }

            foreach (Stage stage in activeStages)
            {  
                stage.UpdateByManager(dTime);
            }
        }

        [Conditional("DEBUG")]
        private void UpdateDTimeMultiplier()
        {
            
        }

        public override void Draw(GameTime gameTime)
        {
            float dTime = (float)gameTime.ElapsedGameTime.TotalSeconds * dTimeManager.DTimeMultiplier;

            foreach (Stage stage in activeStages)
            {
                if (!stage.CoveredByOther)
                {
                    stage.Draw(dTime);
                }
            }
        }
    }
}
